/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <hi_uart.h>
#include "cmsis_os2.h"
#include "energy.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_demo_def.h"

#define ISR_GPIO 8
#define UART_BAUD_RATE 4800
#define UART_DATA_BITS 8
#define UART_STOP_BITS 1
#define Read_ID 0x01

unsigned char Tx_Buffer[8] = {0};
unsigned char Rx_Buffer[40] = {0};
unsigned char Reset_Buffer[11] = {0};
uint32_t g_ReceivedDatalen = 0;

unsigned int calccrc(unsigned char crcbuf, unsigned int crc)
{
    unsigned char i;
    unsigned char chk;
    crc = crc ^ crcbuf;
    for (i = 0; i < 8; i++)
    {
        chk = (unsigned char)(crc & 1);
        crc = crc >> 1;
        crc = crc & 0x7fff;
        if (chk == 1)
            crc = crc ^ 0xa001;
        crc = crc & 0xffff;
    }
    return crc;
}
unsigned int chkcrc(unsigned char *buf, unsigned char len)
{
    unsigned char hi, lo;
    unsigned int i;
    unsigned int crc;
    crc = 0xFFFF;
    for (i = 0; i < len; i++)
    {
        crc = calccrc(*buf, crc);
        buf++;
    }
    hi = (unsigned char)(crc % 256);
    lo = (unsigned char)(crc / 256);
    crc = (((unsigned int)(hi)) << 8) | lo;
    return crc;
}

void send_data(void)
{
    union crcdata
    {
        unsigned int word16;
        unsigned char byte[2];
    } crcnow;
    Tx_Buffer[0] = Read_ID; //模块的 ID 号，默认 ID 为 0x01
    Tx_Buffer[1] = 0x03;
    Tx_Buffer[2] = 0x00;
    Tx_Buffer[3] = 0x48;
    Tx_Buffer[4] = 0x00;
    Tx_Buffer[5] = 0x06;
    crcnow.word16 = chkcrc(Tx_Buffer, 6);
    Tx_Buffer[6] = crcnow.byte[1]; // CRC 效验低字节在前
    Tx_Buffer[7] = crcnow.byte[0];
    hi_uart_write(HI_UART_IDX_1, (hi_u8 *)Tx_Buffer, sizeof(Tx_Buffer)); //发送 8 个数据
}

static int read_data()
{
    g_ReceivedDatalen = hi_uart_read(HI_UART_IDX_1, (hi_u8 *)Rx_Buffer, sizeof(Rx_Buffer));
    if (g_ReceivedDatalen > 0)
    {
        printf("rcvData len:%d\n", g_ReceivedDatalen);
    }
    else
    {
        printf(" send_data no return!\r\n");
        return HI_ERR_FAILURE;
    }
    return HI_ERR_SUCCESS;
}

int Analysis_data(long *Voltage_data, long *Current_data, long *Power_data, long *Energy_data, long *PF_data, long *CO2_data)
{
    send_data();
    read_data();
    unsigned char i;
    union crcdata
    {
        unsigned int word16;
        unsigned char byte[2];
    } crcnow;

    if (Rx_Buffer[0] == Read_ID) //确认 ID 正确
    {
        crcnow.word16 = chkcrc(Rx_Buffer, g_ReceivedDatalen - 2);                                                         // g_ReceivedDatalen 是接收数据总长度
        if ((crcnow.byte[0] == Rx_Buffer[g_ReceivedDatalen - 1]) && (crcnow.byte[1] == Rx_Buffer[g_ReceivedDatalen - 2])) //确认 CRC 校验正确
        {
            *Voltage_data = (((unsigned long)(Rx_Buffer[3])) << 24) | (((unsigned long)(Rx_Buffer[4])) << 16) | (((unsigned long)(Rx_Buffer[5])) << 8) | Rx_Buffer[6];
            *Current_data = (((unsigned long)(Rx_Buffer[7])) << 24) | (((unsigned long)(Rx_Buffer[8])) << 16) | (((unsigned long)(Rx_Buffer[9])) << 8) | Rx_Buffer[10];
            *Power_data = (((unsigned long)(Rx_Buffer[11])) << 24) | (((unsigned long)(Rx_Buffer[12])) << 16) | (((unsigned long)(Rx_Buffer[13])) << 8) | Rx_Buffer[14];
            *Energy_data = (((unsigned long)(Rx_Buffer[15])) << 24) | (((unsigned long)(Rx_Buffer[16])) << 16) | (((unsigned long)(Rx_Buffer[17])) << 8) | Rx_Buffer[18];
            *PF_data = (((unsigned long)(Rx_Buffer[19])) << 24) | (((unsigned long)(Rx_Buffer[20])) << 16) | (((unsigned long)(Rx_Buffer[21])) << 8) | Rx_Buffer[22];
            *CO2_data = (((unsigned long)(Rx_Buffer[23])) << 24) | (((unsigned long)(Rx_Buffer[24])) << 16) | (((unsigned long)(Rx_Buffer[25])) << 8) | Rx_Buffer[26];
        }
        else
        {
            printf("crc error");
            return -1;
        }
    }
    else
    {
        printf("id error");
        return -1;
    }

    return 0;
}

void reset_data(void)
{
    union crcdata
    {
        unsigned int word16;
        unsigned char byte[2];
    } crcnow;
    Reset_Buffer[0] = Read_ID; //模块的 ID 号，默认 ID 为 0x01
    Reset_Buffer[1] = 0x10;
    Reset_Buffer[2] = 0x00;
    Reset_Buffer[3] = 0x4B;
    Reset_Buffer[4] = 0x00;
    Reset_Buffer[5] = 0x01;
    Reset_Buffer[6] = 0x02;
    Reset_Buffer[7] = 0x00;
    Reset_Buffer[8] = 0x00;
    crcnow.word16 = chkcrc(Reset_Buffer, 9);
    Reset_Buffer[9] = crcnow.byte[1]; // CRC 效验低字节在前
    Reset_Buffer[10] = crcnow.byte[0];
    hi_uart_write(HI_UART_IDX_1, (hi_u8 *)Reset_Buffer, sizeof(Reset_Buffer));
    Reset_Buffer[3] = 0x4D;
    hi_uart_write(HI_UART_IDX_1, (hi_u8 *)Reset_Buffer, sizeof(Reset_Buffer));
}

static void Get_pulse(char *arg)
{
    if (g_gpioIsrController.controller.callback != NULL)
    {
        g_gpioIsrController.controller.callback(arg);
    }
}

int Set_Counter(GpioIsrCallback callback, char *arg)
{
    g_gpioIsrController.controller.callback = callback;
    g_gpioIsrController.controller.args = arg;
    IoTGpioRegisterIsrFunc(ISR_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_RISE_LEVEL_HIGH, Get_pulse, arg);

    return 0;
}

static int InitPower()
{
    // 设置GPIO_14的复用功能为普通GPIO
    if (IoTGpioSetFunc(14, IOT_GPIO_FUNC_GPIO_14_GPIO) != 0)
    {
        RaiseLog(LOG_LEVEL_ERR, "IoTGpioSetFunc IOT_GPIO_FUNC_GPIO_14_GPIO failed! \n");
        return -1;
    }
    // 设置GPIO_14为输出模式
    IoTGpioSetDir(14, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(14, 1);
    return 0;
}

static int InitGpioIsr()
{
    IoTGpioInit(ISR_GPIO);
    if (IoTGpioSetFunc(ISR_GPIO, IOT_GPIO_FUNC_GPIO_8_GPIO) != 0)
    {
        RaiseLog(LOG_LEVEL_ERR, "IoTGpioSetFunc IOT_GPIO_FUNC_GPIO_8_GPIO failed! \n");
        return -1;
    }
    // 设置GPIO_8为输入模式
    IoTGpioSetDir(ISR_GPIO, IOT_GPIO_DIR_IN);
    IoTGpioSetPull(ISR_GPIO, IOT_GPIO_PULL_DOWN);
    return 0;
}

void app_uart_init(void)
{

    hi_uart_attribute uart_attr = {
        .baud_rate = UART_BAUD_RATE, /* baud_rate: 4800 */
        .data_bits = UART_DATA_BITS, /* data_bits: 8bits */
        .stop_bits = UART_STOP_BITS,
        .parity = 0,
    };

    /* Initialize uart driver */
    hi_u32 ret = hi_uart_init(HI_UART_IDX_1, &uart_attr, HI_NULL);
    if (ret != HI_ERR_SUCCESS)
    {
        printf("Failed to init uart! Err code = %d\n", ret);
        return;
    }
}

int EnergyInit(void)
{
    if (InitGpioIsr() < 0)
    {
        RaiseLog(LOG_LEVEL_ERR, "InitGpioIsr failed! \n");
        return -1;
    }
    if (InitPower() < 0)
    {
        RaiseLog(LOG_LEVEL_ERR, "InitPower failed! \n");
        return -1;
    }
    return 0;
}

int EnergySetPowerStatus(int status)
{
    if (status)
    {
        IoTGpioSetOutputVal(14, 0);
    }
    else
    {
        IoTGpioSetOutputVal(14, 1);
    }
    return 0;
}

void EnergyDeinit(void)
{
}
